home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / PKTDRVR.C < prev    next >
Text File  |  1993-08-09  |  14KB  |  526 lines

  1. /* Driver for FTP Software's packet driver interface. (PC specific code)
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <dos.h>
  6. #include "global.h"
  7. #include "config.h"
  8. #ifdef PACKET
  9. #include "proc.h"
  10. #include "mbuf.h"
  11. #include "netuser.h"
  12. #include "enet.h"
  13. #include "arcnet.h"
  14. #include "ax25.h"
  15. #include "slip.h"
  16. #include "kiss.h"
  17. #include "iface.h"
  18. #include "ec.h"
  19. #include "arp.h"
  20. #include "trace.h"
  21. #include "pktdrvr.h"
  22. #include "devparam.h"
  23.  
  24. static long near access_type __ARGS((int intno,int if_class,int if_type,
  25.     int if_number, char *type,unsigned typelen,
  26.     INTERRUPT (*receiver) __ARGS((void)) ));
  27. static int near driver_info __ARGS((int intno,int handle,int *version,
  28.     int *class,int *type,int *number,int *basic));
  29. static int near release_type __ARGS((int intno,int handle));
  30. static int near get_address __ARGS((int intno,int handle,char *buf,int len));
  31. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  32. static int pk_stop __ARGS((struct iface *iface,int tmp));
  33. static int near send_pkt __ARGS((int intno,char *buffer,unsigned length));
  34.  
  35. #ifdef    ARCNET
  36. static char arcip[] = {ARC_IP}, arcarp[] = {ARC_ARP};
  37. #endif
  38.  
  39. INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  40. static struct pktdrvr Pktdrvr[PK_MAX];
  41. static int Derr = 0;
  42. static char Pkt_sig[] = "PKT DRVR";    /* Packet driver signature */
  43.  
  44. #ifdef SLFP
  45. /*
  46.  * Send routine for packet driver
  47.  */
  48. int
  49. pk_send(
  50. struct mbuf *bp,        /* Buffer to send */
  51. struct iface *iface,    /* Pointer to interface control block */
  52. int32 gateway,            /* Ignored  */
  53. int prec,
  54. int del,
  55. int tput,
  56. int rel)
  57. {
  58.     if(iface == NULLIF){
  59.         free_p(bp);
  60.         return -1;
  61.     }
  62.     return (*iface->raw)(iface,bp);
  63. }
  64. #endif
  65.  
  66. /* Send raw packet (caller provides header) */
  67. static int
  68. pk_raw(
  69. struct iface *iface,    /* Pointer to interface control block */
  70. struct mbuf *bp)        /* Data field */
  71. {
  72.     struct mbuf *bp1;
  73.  
  74.     struct pktdrvr *pp = &Pktdrvr[iface->dev];
  75.     int16 size = len_p(bp);
  76.  
  77.     /* Perform class-specific processing, if any */
  78.     switch(pp->class){
  79. #ifdef ETHER
  80.     case CL_ETHERNET:
  81.         if(size < RUNT){
  82.             /* Pad the packet out to the minimum */
  83.             bp1 = alloc_mbuf(RUNT-size);
  84.             bp1->cnt = RUNT-size;
  85.             append(&bp,bp1);
  86.             size = RUNT;
  87.         }
  88.         break;
  89. #endif
  90.     case CL_KISS:
  91.         /* This *really* shouldn't be done here, but it was the
  92.          * easiest way. Put the type field for KISS TNC on front.
  93.          */
  94.         bp1 = pushdown(bp,1);
  95.         bp = bp1;
  96.         bp->data[0] = PARAM_DATA;
  97.         size++;
  98.         break;
  99.     }
  100.     dump(iface,IF_TRACE_OUT,pp->class,bp);
  101.  
  102.     if(bp->next != NULLBUF){
  103.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  104.         bp1 = copy_p(bp,size);
  105.         free_p(bp);
  106.         if((bp = bp1) == NULLBUF)
  107.             return -1;
  108.     }
  109.     send_pkt(pp->intno,bp->data,bp->cnt);
  110.     free_p(bp);
  111.     return 0;
  112. }
  113.  
  114. /* Packet driver receive routine. Called from an assembler hook that pushes
  115.  * the caller's registers on the stack so we can access and modify them.
  116.  * This is a rare example of call-by-location in C.
  117.  */
  118. INTERRUPT
  119. pkint(
  120. unsigned short bp,
  121. unsigned short di,
  122. unsigned short si,
  123. unsigned short ds,
  124. unsigned short es,
  125. unsigned short dx,
  126. unsigned short cx,
  127. unsigned short bx,
  128. unsigned short ax,
  129. unsigned short ip,
  130. unsigned short cs,
  131. unsigned short flags,
  132. int dev)
  133. {
  134.     struct phdr phdr;
  135.     struct pktdrvr *pp = &Pktdrvr[dev];
  136.  
  137.     if(dev < 0 || dev >= PK_MAX || pp->iface == NULLIF)
  138.         return;    /* Unknown device */
  139.  
  140.     switch(ax){
  141.     case 0:                     /* Space allocate call */
  142.         pp->buffer = alloc_mbuf(cx + sizeof(struct phdr));
  143.         es = FP_SEG(pp->buffer->data);
  144.         di = FP_OFF(pp->buffer->data + sizeof(struct phdr));
  145.         pp->buffer->cnt = cx + sizeof(struct phdr);
  146.         phdr.iface = pp->iface;
  147.         phdr.type = pp->class;
  148.         memcpy(&pp->buffer->data[0],(char *)&phdr,sizeof(struct phdr));
  149.         break;
  150.     case 1:                        /* Packet complete call */
  151.         enqueue(&Hopper,pp->buffer);
  152.         pp->buffer = NULLBUF;
  153.     default:
  154.         break;
  155.     }
  156. }
  157.  
  158. /* Shut down the packet interface */
  159. static int
  160. pk_stop(struct iface *iface,int tmp)
  161. {
  162.     struct pktdrvr *pp = &Pktdrvr[iface->dev];
  163.  
  164.     /* Call driver's release_type() entry */
  165.     if(release_type(pp->intno,pp->handle1) == -1)
  166.         tprintf("%s: release_type error code %u\n",iface->name,Derr);
  167.  
  168. #if defined(ETHER) || defined (ARCNET)
  169.     if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  170.         release_type(pp->intno,pp->handle2);
  171.         release_type(pp->intno,pp->handle3);
  172.     }
  173. #endif
  174.  
  175.     pp->iface = NULLIF;
  176.     return 0;
  177. }
  178.  
  179. /* Attach a packet driver to the system
  180.  * argv[0]: hardware type, must be "packet"
  181.  * argv[1]: software interrupt vector, e.g., x7e
  182.  * argv[2]: interface label, e.g., "trw0"
  183.  * argv[3]: buffer size - not used
  184.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  185.  * argv[5]: optional ipaddr
  186.  */
  187. int
  188. pk_attach(int argc,char *argv[],void *p)
  189. {
  190.     struct iface *if_pk;
  191.     int class, type, i, xdev;
  192.     unsigned int intno;
  193.     long handle, drvvec;
  194.     char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  195. #ifdef ETHER
  196.     char tmp[25];
  197. #endif
  198. #ifdef ETHER
  199.     char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  200.     char revarptype[] = {REVARP_TYPE >> 8, REVARP_TYPE};
  201. #endif
  202.  
  203.     char sig[8];        /* Copy of driver signature "PKT DRVR" */
  204.     struct pktdrvr *pp;
  205.  
  206. #ifdef AX25
  207.     if(*Mycall == '\0') {
  208.         tputs(Nomycall);
  209.         return -1;
  210.     }
  211. #endif
  212.     if(if_lookup(argv[2]) != NULLIF){
  213.         tprintf(Ifexist,argv[2]);
  214.         return -1;
  215.     }
  216.     for(i = 0; i < PK_MAX; i++) {
  217.         if(Pktdrvr[i].iface == NULLIF)
  218.             break;
  219.     }
  220.     if(i >= PK_MAX){
  221.         tprintf("Max %d packet drivers\n",PK_MAX);
  222.         return -1;
  223.     }
  224.  
  225.     intno = htoi(argv[1]);
  226.     /* Verify that there's really a packet driver there, so we don't
  227.      * go off into the ozone (if there's any left)
  228.      */
  229.     drvvec = (long)getvect(intno);
  230.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  231.         FP_OFF(sig),FP_SEG(sig),strlen(Pkt_sig));
  232.     if(strncmp(sig,Pkt_sig,strlen(Pkt_sig)) != 0){
  233.         tprintf("No packet driver loaded at int 0x%x\n",intno);
  234.         return -1;
  235.     }
  236.     if_pk = mxallocw(sizeof(struct iface));
  237.     if_pk->name = strxdup(argv[2]);
  238.     if_pk->addr = Ip_addr;
  239.     pp = &Pktdrvr[i];
  240.     if_pk->mtu = atoi(argv[4]);
  241.     if_pk->dev = i;
  242.     if_pk->xdev = 0;
  243.     if_pk->raw = pk_raw;
  244.     if_pk->stop = pk_stop;
  245.     pp->intno = intno;
  246.     pp->iface = if_pk;
  247.  
  248.      /* Version 1.08 of the packet driver spec dropped the handle
  249.       * requirement from the driver_info call.  However, if we are using
  250.       * a version 1.05 packet driver, the following call will fail.
  251.        */
  252.      if(driver_info(intno,-1,NULL,&class,&type,NULL,NULL) < 0){
  253.         /* Find out by exhaustive search what class this driver is (ugh) */
  254.         for(class = 1; class <= NCLASS; class++) {
  255.             /* Store handle in temp long so we can tell an
  256.              * error return (-1) from a handle of 0xffff
  257.              */
  258.             handle = access_type(intno,class,ANYTYPE,0,iptype,2,
  259.                 Pkvec[if_pk->dev]);
  260.             if(handle != -1 || Derr == TYPE_INUSE){
  261.                 pp->handle1 = handle;
  262.                 break;
  263.             }
  264.         }
  265.         /* Now that we know, release it and do it all over again with the
  266.          * right type fields
  267.          */
  268.         release_type(intno,pp->handle1);
  269.     }
  270.     switch(class){
  271. #ifdef ETHER
  272.     case CL_ETHERNET:
  273.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  274.             Pkvec[if_pk->dev]);
  275.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  276.             Pkvec[if_pk->dev]);
  277.         pp->handle3 = access_type(intno,class,ANYTYPE,0,revarptype,2,
  278.             Pkvec[if_pk->dev]);
  279.         setencap(if_pk,"Ethernet");
  280.         /* Get hardware Ethernet address from driver */
  281.         if_pk->hwaddr = mxallocw(EADDR_LEN);
  282.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  283.         if(if_pk->hwaddr[0] & 1){
  284.             tprintf("Warning! Iface '%s' has a multicast address:",
  285.              if_pk->name);
  286.             tprintf(" (%s)\n",
  287.              (*if_pk->iftype->format)(tmp,if_pk->hwaddr));
  288.         }
  289.         break;
  290. #endif
  291. #ifdef    ARCNET
  292.     case CL_ARCNET:
  293.         pp->handle1 = access_type(intno,class,ANYTYPE,0,arcip,1,
  294.             Pkvec[if_pk->dev]);
  295.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arcarp,1,
  296.             Pkvec[if_pk->dev]);
  297.         if_pk->send = anet_send;
  298.         if_pk->output = anet_output;
  299.         /* Get hardware ARCnet address from driver */
  300.         if_pk->hwaddr = mxallocw(AADDR_LEN);
  301.         get_address(intno,pp->handle1,if_pk->hwaddr,AADDR_LEN);
  302.         break;
  303. #endif
  304.     case CL_SERIAL_LINE:
  305.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  306.          Pkvec[if_pk->dev]);
  307.         setencap(if_pk,"SLIP");
  308.         break;
  309. #ifdef    AX25
  310.     case CL_KISS:    /* Note that the raw routine puts on the command */
  311.     case CL_AX25:
  312.         for(xdev = 0; xdev < SLIP_MAX; xdev++) {
  313.             if(Slip[xdev].iface == NULLIF)
  314.                 break;
  315.         }
  316.         if(xdev >= SLIP_MAX) {
  317.             tprintf("Max %d slip/asy/nrs devices\n",SLIP_MAX);
  318.             return -1;
  319.         }
  320.         Slip[xdev].iface = if_pk;
  321.         Slip[xdev].kiss[if_pk->port] = if_pk;        /* G1EMM */
  322.  
  323.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  324.             Pkvec[if_pk->dev]);
  325.         setencap(if_pk,"AX25");
  326.         if_pk->hwaddr = strxdup(Mycall);
  327.  
  328.         init_maxheard(if_pk);
  329.         init_flags(if_pk);
  330.         break;
  331. #endif
  332. #ifdef SLFP
  333.     case CL_SLFP:
  334.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  335.          Pkvec[if_pk->dev]);
  336.         if_pk->send = pk_send;
  337.         setencap(if_pk,"SLFP");
  338.         get_address(intno,pp->handle1,(char *)&if_pk->addr,4);
  339.         break;
  340. #endif
  341.     default:
  342.         tprintf("Packet driver has unsupported class %u\n",class);
  343.         xfree(if_pk->name);
  344.         xfree(if_pk);
  345.         return -1;
  346.     }
  347.     pp->class = class;
  348.     if_pk->next = Ifaces;
  349.     Ifaces = if_pk;
  350.     if_pk->niface = Niface++;
  351.  
  352.     return 0;
  353. }
  354.  
  355. static long near
  356. access_type(int intno,int if_class,int if_type,int if_number,char *type,unsigned typelen,INTERRUPT (*receiver)())
  357. {
  358.     union REGS regs;
  359.     struct SREGS sregs;
  360.  
  361.     segread(&sregs);
  362.     regs.h.dl = if_number;                /* Number */
  363.     sregs.ds = FP_SEG(type);            /* Packet type template */
  364.     regs.x.si = FP_OFF(type);
  365.     regs.x.cx = typelen;                /* Length of type */
  366.     sregs.es = FP_SEG(receiver);        /* Address of receive handler */
  367.     regs.x.di = FP_OFF(receiver);
  368.     regs.x.bx = if_type;                /* Type */
  369.     regs.h.ah = ACCESS_TYPE;            /* Access_type() function */
  370.     regs.h.al = if_class;                /* Class */
  371.     int86x(intno,®s,®s,&sregs);
  372.     if(regs.x.cflag) {
  373.         Derr = regs.h.dh;
  374.         return -1;
  375.     }
  376.     return regs.x.ax;
  377. }
  378.  
  379. static int near
  380. release_type(int intno,int handle)
  381. {
  382.     union REGS regs;
  383.  
  384.     regs.x.bx = handle;
  385.     regs.h.ah = RELEASE_TYPE;
  386.     int86(intno,®s,®s);
  387.     if(regs.x.cflag){
  388.         Derr = regs.h.dh;
  389.         return -1;
  390.     }
  391.     return 0;
  392. }
  393.  
  394. static int near
  395. send_pkt(int intno,char *buffer,unsigned length)
  396. {
  397.     union REGS regs;
  398.     struct SREGS sregs;
  399.  
  400.     segread(&sregs);
  401.     sregs.ds = FP_SEG(buffer);
  402.     sregs.es = FP_SEG(buffer);         /* for buggy univation pkt driver - CDY */
  403.     regs.x.si = FP_OFF(buffer);
  404.     regs.x.cx = length;
  405.     regs.h.ah = SEND_PKT;
  406.     int86x(intno,®s,®s,&sregs);
  407.     if(regs.x.cflag){
  408.         Derr = regs.h.dh;
  409.         return -1;
  410.     }
  411.     return 0;
  412. }
  413.  
  414. static int near
  415. driver_info(int intno,int handle,int *version,int *class,int *type,int *number,int *basic)
  416. {
  417.     union REGS regs;
  418.  
  419.     regs.x.bx = handle;
  420.     regs.h.ah = DRIVER_INFO;
  421.     regs.h.al = 0xff;
  422.     int86(intno,®s,®s);
  423.     if(regs.x.cflag){
  424.         Derr = regs.h.dh;
  425.         return -1;
  426.     }
  427.     if(version != NULL)
  428.         *version = regs.x.bx;
  429.     if(class != NULL)
  430.         *class = regs.h.ch;
  431.     if(type != NULL)
  432.         *type = regs.x.dx;
  433.     if(number != NULL)
  434.         *number = regs.h.cl;
  435.     if(basic != NULL)
  436.         *basic = regs.h.al;
  437.     return 0;
  438. }
  439.  
  440. static int near
  441. get_address(int intno,int handle,char *buf,int len)
  442. {
  443.     union REGS regs;
  444.     struct SREGS sregs;
  445.  
  446.     segread(&sregs);
  447.     sregs.es = FP_SEG(buf);
  448.     regs.x.di = FP_OFF(buf);
  449.     regs.x.cx = len;
  450.     regs.x.bx = handle;
  451.     regs.h.ah = GET_ADDRESS;
  452.     int86x(intno,®s,®s,&sregs);
  453.     if(regs.x.cflag){
  454.         Derr = regs.h.dh;
  455.         return -1;
  456.     }
  457.     return 0;
  458. }
  459.  
  460. /*----------------------------------------------------------------------*
  461. *-----------------------------------------------------------------------*/
  462. void pkt_suspend(void)
  463. {
  464. struct pktdrvr *pp;
  465. int i;
  466.       for(i=0;i < PK_MAX;i++){         /* scan the asy structures      */
  467.          pp = &Pktdrvr[i];
  468.          if(pp->iface == NULLIF)
  469.             continue;
  470.          release_type(pp->intno,pp->handle1);
  471.          if(pp->class == CL_ETHERNET || pp->class == CL_ARCNET){
  472.             release_type(pp->intno,pp->handle2);
  473.             release_type(pp->intno,pp->handle3);
  474.          }
  475.       }
  476. }
  477.  
  478. /*----------------------------------------------------------------------*
  479. *-----------------------------------------------------------------------*/
  480. void pkt_restore(void)
  481. {
  482. struct pktdrvr *pp;
  483. int i;
  484.  
  485.    for(i = 0; i < PK_MAX; i++) {
  486.       pp = &Pktdrvr[i];
  487.  
  488.       if(pp->iface == NULLIF)
  489.          continue;
  490.       switch (pp->class)   {
  491. #ifdef XXX
  492.          case CL_ETHERNET:
  493.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,iptype,2, Pkvec[i]);
  494.             pp->handle2 = access_type(pp->intno,pp->class,ANYTYPE,0,arptype,2, Pkvec[i]);
  495.             pp->handle3 = access_type(pp->intno,pp->class,ANYTYPE,0,revarptype,2, Pkvec[i]);
  496.             break;
  497. #endif
  498. #ifdef  ARCNET
  499.          case CL_ARCNET:
  500.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,arcip,1, Pkvec[i]);
  501.             pp->handle2 = access_type(pp->intno,pp->class,ANYTYPE,0,arcarp,1, Pkvec[i]);
  502.             break;
  503. #endif
  504.          case CL_SERIAL_LINE:
  505.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  506.             break;
  507. #ifdef  AX25
  508.          case CL_KISS:     /* Note that the raw routine puts on the command*/
  509.          case CL_AX25:
  510.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  511.             break;
  512. #endif
  513. #ifdef SLFP
  514.          case CL_SLFP:
  515.             pp->handle1 = access_type(pp->intno,pp->class,ANYTYPE,0,NULLCHAR,0, Pkvec[i]);
  516.             break;
  517. #endif
  518.       }
  519.    }
  520. }
  521.  
  522.  
  523. #endif PACKET
  524.  
  525.  
  526.